<html>
<head><meta charset="utf-8"><title>UnstableTransmuteFrom - Zeroable · project-safe-transmute · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/index.html">project-safe-transmute</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html">UnstableTransmuteFrom - Zeroable</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="218189698"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218189698" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218189698">(Nov 29 2020 at 01:19)</a>:</h4>
<p>Another case where <code>TransmuteFrom</code>/<code>Muckable{From,Into}</code> is overly-restrictive: Expressing just that a type can be safely instantiated via <code>mem::zeroed()</code>.</p>
<p><code>UnstableTransmuteFrom</code> provides a foundation for this, too!</p>



<a name="218189838"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218189838" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218189838">(Nov 29 2020 at 01:23)</a>:</h4>
<p>First off, an <code>UnstableFromZeros</code> might be constructed like this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">UnstableFromZeros</span><span class="o">&lt;</span><span class="n">Scope</span><span class="p">,</span><span class="w"> </span><span class="n">Neglect</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">!&gt;</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">Neglect</span>: <span class="nc">TransmuteOptions</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="sd">/// Safely initialize `Self` from zeroed bytes.</span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">zeroed</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="n">Neglect</span>: <span class="nc">SafeTransmuteOptions</span><span class="p">;</span><span class="w"></span>

<span class="w">    </span><span class="sd">/// Unsafely initialize `Self` from zeroed bytes.</span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">unsafe_zeroed</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="cp">#[derive(Copy, Clone)]</span><span class="w"></span>
<span class="cp">#[repr(u8)]</span><span class="w"></span>
<span class="k">enum</span> <span class="nc">Zero</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">Zero</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="k">u8</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">unsafe</span><span class="w"> </span><span class="k">impl</span><span class="o">&lt;</span><span class="n">Dst</span><span class="p">,</span><span class="w"> </span><span class="n">Scope</span><span class="p">,</span><span class="w"> </span><span class="n">Neglect</span><span class="o">&gt;</span><span class="w"> </span><span class="n">UnstableFromZeros</span><span class="o">&lt;</span><span class="n">Scope</span><span class="p">,</span><span class="w"> </span><span class="n">Neglect</span><span class="o">&gt;</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Dst</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">Dst</span>: <span class="nc">UnstableTransmuteFrom</span><span class="o">&lt;</span><span class="p">[</span><span class="n">Zero</span><span class="p">;</span><span class="w"> </span><span class="kt">usize</span>::<span class="n">MAX</span><span class="p">],</span><span class="w"> </span><span class="n">Scope</span><span class="p">,</span><span class="w"> </span><span class="n">Neglect</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">Neglect</span>: <span class="nc">TransmuteOptions</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">fn</span> <span class="nf">zeroed</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"></span>
<span class="w">    </span><span class="k">where</span><span class="w"></span>
<span class="w">        </span><span class="n">Neglect</span>: <span class="nc">SafeTransmuteOptions</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">[</span><span class="n">Zero</span><span class="p">;</span><span class="w"> </span><span class="n">size_of</span>::<span class="o">&lt;</span><span class="bp">Self</span><span class="o">&gt;</span><span class="p">].</span><span class="n">transmute_into</span><span class="p">()</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>

<span class="w">    </span><span class="k">unsafe</span><span class="w"> </span><span class="k">fn</span> <span class="nf">unsafe_zeroed</span><span class="p">()</span><span class="w"> </span>-&gt; <span class="nc">Self</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">        </span><span class="p">[</span><span class="n">Zero</span><span class="p">;</span><span class="w"> </span><span class="n">size_of</span>::<span class="o">&lt;</span><span class="bp">Self</span><span class="o">&gt;</span><span class="p">].</span><span class="n">unsafe_transmute_into</span><span class="p">()</span><span class="w"></span>
<span class="w">    </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>Given that, you can <em>really</em> quickly reduce unsafety in a library by simply replacing <code>mem::zeroed()</code> with <code>zeroed!()</code>:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">pub</span><span class="w"> </span><span class="kr">macro</span><span class="w"> </span><span class="n">zeroed</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="p">{</span><span class="w"> </span><span class="k">struct</span> <span class="nc">Here</span><span class="p">;</span><span class="w"> </span><span class="n">UnstableTransmuteFrom</span>::<span class="o">&lt;</span><span class="n">Here</span><span class="o">&gt;</span>::<span class="n">zeroed</span><span class="p">()</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="218190001"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218190001" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218190001">(Nov 29 2020 at 01:28)</a>:</h4>
<p>Of course, that only covers safety, not semver stability. We can communicate stable zero-initializability in a few ways.</p>



<a name="218190004"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218190004" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218190004">(Nov 29 2020 at 01:28)</a>:</h4>
<p>First, we can simply document our guarantee and (for our own benefit) assert:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">struct</span> <span class="nc">Here</span><span class="p">;</span><span class="w"></span>
<span class="n">assert_impl_all</span><span class="o">!</span><span class="p">(</span><span class="n">MyType</span>: <span class="nc">UnstableFromZeros</span><span class="o">&lt;</span><span class="n">Here</span><span class="o">&gt;</span><span class="p">)</span><span class="w"></span>
</code></pre></div>



<a name="218190139"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218190139" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218190139">(Nov 29 2020 at 01:33)</a>:</h4>
<p>Second, we can define a <code>Muckable</code>-style system; e.g.:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">unsafe</span><span class="w"> </span><span class="k">impl</span><span class="w"> </span><span class="n">Zeroable</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">MyType</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
</code></pre></div>
<p>...where:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="sd">/// A marker trait signaling that transmutation from zeros is stable</span>
<span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">Zeroable</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>

<span class="k">pub</span><span class="w"> </span><span class="k">unsafe</span><span class="w"> </span><span class="k">trait</span><span class="w"> </span><span class="n">AlwaysFromZeros</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">Neglect</span>: <span class="nc">TransmuteOptions</span><span class="w"></span>
<span class="p">{</span><span class="w"></span>
<span class="w">  </span><span class="o">..</span><span class="p">.</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>

<span class="k">unsafe</span><span class="w"> </span><span class="k">impl</span><span class="o">&lt;</span><span class="n">Dst</span><span class="p">,</span><span class="w"> </span><span class="n">Scope</span><span class="p">,</span><span class="w"> </span><span class="n">Neglect</span><span class="o">&gt;</span><span class="w"> </span><span class="n">AlwaysFromZeros</span><span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="n">Dst</span><span class="w"></span>
<span class="k">where</span><span class="w"></span>
<span class="w">    </span><span class="n">Dst</span>: <span class="nc">Zeroable</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">Dst</span>: <span class="nc">UnstableFromZeros</span><span class="o">&lt;</span><span class="p">[</span><span class="n">Zero</span><span class="p">;</span><span class="w"> </span><span class="kt">usize</span>::<span class="n">MAX</span><span class="p">],</span><span class="w"> </span><span class="o">!</span><span class="p">,</span><span class="w"> </span><span class="n">NeglectVisibility</span><span class="o">&gt;</span><span class="p">,</span><span class="w"></span>
<span class="p">{}</span><span class="w"></span>
</code></pre></div>



<a name="218190200"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218190200" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218190200">(Nov 29 2020 at 01:35)</a>:</h4>
<p>(Stability is hard! But, with <code>UnstableTransmuteFrom</code>, <em>we</em> don't need to solve it in libcore on our first go.)</p>



<a name="218476089"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218476089" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Elichai Turkel <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218476089">(Dec 01 2020 at 20:22)</a>:</h4>
<p>Isn't that expressed by allowing transmute from <code>[u8; size_of::&lt;T&gt;()] </code>?</p>



<a name="218477336"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218477336" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218477336">(Dec 01 2020 at 20:32)</a>:</h4>
<p>It is. I'm referring to the <em>contract</em> of <code>Zeroable</code>. The contract of bytemuck's <code>Zeroable</code> is that you promise that your type can be instantiated with <code>mem::zeroed()</code>. You're allowed to change all other aspects of your type's layout so long as you maintain that contract.</p>
<p>In contrast, the <code>Muckable</code> approach promises that you <em>won't</em> change <strong>any</strong> aspects of your type's layout.</p>



<a name="218506297"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218506297" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218506297">(Dec 02 2020 at 01:45)</a>:</h4>
<p><span class="user-mention" data-user-id="117495">@rpjohnst</span> <em>Maybe</em> an archetype-based approach might provide an elegant solution to this problem (assuming we can make it sound), but I'm not seeing one with <code>Muckable</code>.</p>



<a name="218506633"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218506633" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> rpjohnst <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218506633">(Dec 02 2020 at 01:50)</a>:</h4>
<p>Well what I was imagining with <code>Muckable</code> here was, you make the type private and <code>Muckable</code>, and then you impl some sort of <code>FromZeros</code> trait for a newtype wrapper which exploits the private <code>Muckable</code>-ness to safely convert a bunch of zeros to an instance of the newtype.</p>



<a name="218506669"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218506669" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> rpjohnst <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218506669">(Dec 02 2020 at 01:51)</a>:</h4>
<p>The big hammer of <code>Muckable</code> opts you into safe transmute in any form, and then the <code>FromZeroes</code> trait opts the public API into just one kind of transmute, with the private <code>Muckable</code> as a witness that it's valid.</p>



<a name="218506746"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218506746" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Jack Wrenn <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218506746">(Dec 02 2020 at 01:52)</a>:</h4>
<p>How do you make <code>FromZeros</code> safe though?</p>



<a name="218507336"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218507336" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> rpjohnst <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218507336">(Dec 02 2020 at 02:03)</a>:</h4>
<p>You define it in such a way that any <code>impl</code> of it must itself exploit a relevant property of the type which is visible to the <code>impl</code>. So, to illustrate (this is probably not workable), imagine something like <code>trait FromZeroes { fn from_zeroes(zeros: [Zero; bla]) -&gt; Self; }</code>.</p>



<a name="218507446"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom%20-%20Zeroable/near/218507446" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> rpjohnst <a href="https://rust-lang.github.io/zulip_archive/stream/216762-project-safe-transmute/topic/UnstableTransmuteFrom.20-.20Zeroable.html#218507446">(Dec 02 2020 at 02:05)</a>:</h4>
<p>Inside the module impl-ing <code>FromZeroes</code> for type <code>Foo</code>, the compiler will let you do any transmute that is valid for <code>Foo</code>. Outside, that ability is not accessible, but the <code>FromZeroes</code> trait will use that ability on your behalf.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>